﻿/* Simple Player class
 * Holds a List of 5 dies. 
 * playerScore and playerCombinations indexes:
 * 0 - Ones
 * 1 - Twos
 * 2 - Threes
 * 3 - Fours
 * 4 - Fives
 * 5 - Sixes
 * 6 - Temporary score holder and check; DO NOT USE IN SetPlayerCombinations!
 * 7 - First pair
 * 8 - Second pair
 * 9 - Three of a kind
 * 10 - Four of a kind
 * 11 - Full house
 * 12 - Small straight
 * 13 - Big straight
 * 14 - Chance
 * 15 - Generale */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GeneralTheGame
{
    public class Player
    {
        private List<Die> playerDice = new List<Die>();
        private string playerName;
        private int[] playerScore = new int[16];
        private ConsoleColor playerColor;
        private List<bool> playerCombinations = new List<bool>();
        private bool isCurrentPlayer;

        public List<Die> PlayerDice
        {
            get { return this.playerDice; }
        }

        public string PlayerName
        {
            get { return this.playerName; }
        }

        // Holds the Color of the player's dice if we choose to implement color change

        public ConsoleColor PlayerColor
        {
            get { return this.playerColor; }
        }

        public List<bool> PlayerCombinations
        {
            get { return this.playerCombinations; }
        }

        public int[] PlayerScore
        {
            get { return this.playerScore; }
        }

        public int TotalPlayerScore
        {
            get
            {
                int totalSum = 0;
                for (int i = 6; i < this.playerScore.Length; i++)
                {
                    totalSum += this.playerScore[i];
                }

                return totalSum;
            }
        }

        public int TemporaryPlayerScore
        {
            get { return this.playerScore[6]; }
        }

        // Initialise player object and add 5 dice to the playerDice collection
        public Player(string playerName, ConsoleColor color)
        {
            this.playerName = playerName;
            this.playerColor = color;
            for (int i = 0; i < 5; i++)
            {
                this.playerDice.Add(new Die());
            }

            // Fill cominations and score collections
            // Each index of the combinations collection corresponds to the same index in the score collection
            // E.G. in playerCombinations[0] is Ones and is by default false (as in not set by the player) and the corresponding
            // score is playerScore[0] which is 0 since it's not set.
            for (int i = 0; i < 16; i++)
            {
                this.playerCombinations.Add(false);
                this.playerScore[i] = 0;
            }
        }

        public Player()
        {
            // TODO: Complete member initialization
        }

        public bool IsCurrentPlayer
        {
            // TODO: Complete member initialization
            get { return this.isCurrentPlayer; }
            set { this.isCurrentPlayer = value; }
        }

        // Method that re-throws the player selected dice
        // Accepts a list of the numbers of the selected dice
        // E.G. Player selects to rethrow dice number 1, 2 and 5
        // Parse in a List<int> {1, 2, 5}
        // Rethrow dice number 1, 2 and 5 in the playerDice collection
        public void ThrowDice(List<int> diceNumber)
        {
            for (int i = 0; i < diceNumber.Count; i++)
            {
                // Checks for valid dice number input.
                // Decrement 1 to accomodate for player selection in the range [1 ... 5] and collection enumeration [0 ... 4]
                int currentDiceNumber = diceNumber[i] - 1;
                if (currentDiceNumber < 5 && currentDiceNumber >= 0)
                {
                    this.PlayerDice[currentDiceNumber].ThrowDie();
                }
                else
                {
                    throw new ArgumentException("The selected dice was not in the range [1 ... 5]");
                }
            }
        }


        // Roll all player dice
        public void RollAllDice()
        {
            for (int i = 0; i < this.playerDice.Count; i++)
            {
                this.playerDice[i].ThrowDie();
            }
        }

        // Returns the last throw of the selected die
        public int GetLastDieThrow(int dieNumber)
        {
            if (dieNumber > 5 || dieNumber < 1)
            {
                throw new ArgumentException("The number of the selected die must be in the range [1 ... 5]");
            }
            else
            {
                return this.playerDice[dieNumber - 1].GetLastThrow();
            }
        }


        // Completes the selected combination by setting it true
        // int combination holds the number of the combination in the range [0 ... 14]
        // int score holds the accumulated score by the combination
        public bool SetPlayerCombination(int combination, int score)
        {
            bool result;
            if (combination > 15 || combination < 0)
            {
                throw new ArgumentException("The entered combination must be in the range [0 ... 15]");
            }
            else
            {
                // Check if the entered combination is from 0 to 5 (between Ones and Sixes)
                if (combination >= 0 && combination <= 5)
                {
                    if (this.playerCombinations[combination] == true)
                    {
                        return false;
                    }
                    // Set selected combination to true and add the playerscore to the corresponding score index
                    this.playerCombinations[combination] = true;
                    this.playerScore[combination] = score;

                    // recaulculate the temporary score
                    this.playerScore[6] += score;

                    // If all mandatory combinations are filled and the the temporary score is negative subtract 50 points from it
                    if (this.CheckTemporaryScore() && this.TemporaryPlayerScore < 0)
                    {
                        this.playerScore[6] -= 50;
                    }

                    result = true;
                }

                // If not, just register the combination and set it's score
                else
                {
                    if (this.playerCombinations[combination + 1] == true)
                    {
                        return false;
                    }
                    this.playerScore[combination + 1] = score;
                    this.playerCombinations[combination + 1] = true;

                    result = true;
                }
            }

            return result;
        }

        // Checks if all the mandatory combinations are filled
        public bool CheckTemporaryScore()
        {
            return !this.playerCombinations.GetRange(0, 6).Contains(false);
        }
    }
}
